package com.liliudong.template.biz.service.sys.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.liliudong.template.biz.mapper.sys.SysDictMapper;
import com.liliudong.template.biz.service.sys.SysDictItemService;
import com.liliudong.template.biz.service.sys.SysDictService;
import com.liliudong.template.common.constant.ExMessage;
import com.liliudong.template.common.convert.sys.SysDictConvert;
import com.liliudong.template.common.convert.sys.SysDictItemConvert;
import com.liliudong.template.common.request.sys.SysDictAddRequest;
import com.liliudong.template.common.request.sys.SysDictModifyRequest;
import com.liliudong.template.common.request.sys.SysDictPageRequest;
import com.liliudong.template.common.entity.sys.SysDict;
import com.liliudong.template.common.entity.sys.SysDictItem;
import com.liliudong.template.common.exception.BizException;
import com.liliudong.template.common.response.sys.SysDictDetailResponse;
import com.liliudong.template.common.response.sys.SysDictListResponse;
import com.liliudong.template.common.response.sys.SysDictPageResponse;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.liliudong.template.common.entity.sys.table.SysDictTableDef.SYS_DICT;

/**
 * 服务实现
 *
 * @author liudo
 * @date 2024-08-01 20:14:50
 */
@Service
@RequiredArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict>
        implements SysDictService {

    public static final String SYS_DICT_LIST_CACHE_KEY = "sys:dict:list";

    private final StringRedisTemplate stringRedisTemplate;

    private final SysDictItemService sysDictItemService;

    @Override
    @Transactional
    public void addOne(SysDictAddRequest sysDictAddRequest) {
        stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
        SysDict sysDict = SysDictConvert.INSTANCE.addDTO2Entity(sysDictAddRequest);
        this.save(sysDict);
        List<SysDictAddRequest.SysDictItem> sysDictItemList = sysDictAddRequest.getSysDictItemList();
        if (CollUtil.isNotEmpty(sysDictItemList)) {
            List<SysDictItem> sysDictItems = SysDictItemConvert.INSTANCE.sysDictAddDTOSysDictItemList2EntityList(sysDictItemList);
            sysDictItemService.saveBathByDictId(sysDict.getId(), sysDictItems);
        }
    }

    @Override
    public void deleteById(Long id) {
        stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
        long count = sysDictItemService.countByDictId(id);
        if (count > 0) {
            throw new BizException(ExMessage.DICT_UNION_ITEM);
        }
        removeById(id);
    }

    @Override
    @Transactional
    public void modifyById(Long id, SysDictModifyRequest sysDictModifyRequest) {
        stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
        SysDict sysDict = SysDictConvert.INSTANCE.modifyDTO2Entity(sysDictModifyRequest);
        sysDict.setId(id);
        updateById(sysDict);
        sysDictItemService.removeByDictId(id);
        List<SysDictModifyRequest.SysDictItem> sysDictItemList = sysDictModifyRequest.getSysDictItemList();
        if (CollUtil.isNotEmpty(sysDictItemList)) {
            List<SysDictItem> sysDictItems = SysDictItemConvert.INSTANCE.sysDictModifyDTOSysDictItemList2EntityList(sysDictItemList);
            sysDictItemService.saveBathByDictId(id, sysDictItems);
        }
    }

    @Override
    public SysDictDetailResponse detailById(Long id) {
        SysDictDetailResponse sysDictDetailVO = this.getOneAs(QueryWrapper.create().where(SYS_DICT.ID.eq(id)), SysDictDetailResponse.class);
        if (Objects.isNull(sysDictDetailVO)) {
            throw new BizException(ExMessage.DICT_NOT_EXIST);
        }
        List<SysDictItem> sysDictItemList = sysDictItemService.listByDictId(sysDictDetailVO.getId());
        sysDictDetailVO.setSysDictItemList(sysDictItemList);
        return sysDictDetailVO;
    }

    @Override
    public Page<SysDictPageResponse> queryPage(Long page, Long size, SysDictPageRequest sysDictPageRequest) {
        return queryChain()
                .orderBy(SYS_DICT.CREATED_AT.desc())
                .pageAs(Page.of(page, size), SysDictPageResponse.class);
    }

    @Override
    public List<SysDictListResponse> queryList() {
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String dictListStr = valueOperations.get(SYS_DICT_LIST_CACHE_KEY);
        if (StrUtil.isNotBlank(dictListStr)) {
            return JSON.parseArray(dictListStr, SysDictListResponse.class);
        }
        List<SysDictListResponse> sysDictListVOList = listAs(QueryWrapper.create(), SysDictListResponse.class);
        if (CollUtil.isEmpty(sysDictListVOList)) {
            return List.of();
        }
        List<Long> dictIds = sysDictListVOList.stream().map(SysDictListResponse::getId).toList();
        Map<Long, List<SysDictItem>> dictIdMap = sysDictItemService.listMapsByDictIds(dictIds);

        sysDictListVOList.forEach(sysDictListVO -> sysDictListVO.setChildren(dictIdMap.get(sysDictListVO.getId())));
        valueOperations.set(SYS_DICT_LIST_CACHE_KEY, JSON.toJSONString(sysDictListVOList));
        return sysDictListVOList;
    }
}
